#lang racket

;; Entry point for the sudoku solver. Defines test boards and the solve function
;; Uses: (solve board)
;;       (solve board2)
;; By Spencer Hale
;; Some small modifications by Theresa Wellington

(require "ForceMove.scm")
(require "Elimination.scm")
(require "PossibilityMatrix.scm")
(require "PairElimination.scm")
(require "RowBoxColumnBox.scm")
(require "Output.scm")
(require "Tests.scm")


;starting function
(define solve
  (lambda (matrix)
    (let ((possstart (makevectorbase 9 #t))) ;sets up possibility matrix of designated size, with all values initialized as #t.
      (let ((possvec (setpossibilitiesinitial matrix possstart 0 0))) ; Goes through puzzle matrix analyzing given numbers, and sets possibility vector values to #f where necessary
        (if (tryToSolve matrix possvec 0) matrix ;solve 3 cycles through every algorithm available until the puzzle is solved
            #f)))))


;loops through all available algorithms until solved
(define tryToSolve
  (lambda (matrix possvec count)
    (if (equal? count 5) #f
    (if (solveForceMove matrix possvec 0 0) #t
        (and (solveElimination matrix possvec)
             (if (solveForceMove matrix possvec 0 0) #t
                 (and (rowBox possvec 0 0 1)
                 (colBox possvec 0 0 1)
                 (pairElimination possvec)
                 (tryToSolve matrix possvec (+ count 1)))))))))

;; input
  
(define board
  (vector
   (vector 0 0 2 0 5 0 9 0 6)
   (vector 9 0 3 6 0 0 0 0 0)
   (vector 6 0 0 0 0 8 2 0 0)
   (vector 0 0 9 0 7 2 0 0 4)
   (vector 0 5 0 0 0 0 0 7 0)
   (vector 4 0 0 1 8 0 5 0 0)
   (vector 0 0 4 8 0 0 0 0 1)
   (vector 0 0 0 0 0 1 3 0 2)
   (vector 1 0 7 0 6 0 4 0 0)))

(define board2
  (vector
    (vector 3 0 0 7 2 4 0 0 0)
    (vector 0 2 5 0 0 0 0 0 0)
    (vector 0 0 7 1 3 5 0 0 0)
    (vector 7 0 0 0 0 3 0 6 0)
    (vector 8 0 1 0 6 0 4 0 7)
    (vector 0 3 0 4 0 0 0 0 5)
    (vector 0 0 0 9 1 8 3 0 0)
    (vector 0 0 0 0 0 0 9 7 0)
    (vector 0 0 0 2 4 7 0 0 8)))

(define board3 ;simple solvable
  (vector
    (vector 7 9 0 0 0 0 3 0 0)
    (vector 0 0 0 0 0 6 9 0 0)
    (vector 8 0 0 0 3 0 0 7 6)
    (vector 0 0 0 0 0 5 0 0 2)
    (vector 0 0 5 4 1 8 7 0 0)
    (vector 4 0 0 7 0 0 0 0 0)
    (vector 6 1 0 0 9 0 0 0 8)
    (vector 0 0 2 3 0 0 0 0 0)
    (vector 0 0 9 0 0 0 0 5 4)))

(define board4 ;simple solvable
  (vector
   (vector 2 0 4 1 0 0 0 0 0)
   (vector 0 0 0 5 0 3 6 0 7)
   (vector 0 0 0 9 0 0 4 0 0)
   (vector 9 0 0 4 0 0 0 1 0)
   (vector 6 5 0 0 1 0 0 7 4)
   (vector 0 2 0 0 0 8 0 0 9)
   (vector 0 0 9 0 0 5 0 0 0)
   (vector 5 0 2 3 0 1 0 0 0)
   (vector 0 0 0 0 0 4 1 0 2)
   ))

(define board5
  (vector
    (vector 3 2 6 5 0 0 9 7 0)
    (vector 0 0 5 0 0 8 0 0 0)
    (vector 0 7 0 0 2 0 0 5 0)
    (vector 0 0 0 6 0 0 0 0 0)
    (vector 0 5 8 0 7 0 6 1 0)
    (vector 0 0 0 0 0 4 0 0 0)
    (vector 0 1 0 0 8 0 0 3 0)
    (vector 0 0 0 3 0 0 7 0 0)
    (vector 0 3 7 0 0 9 4 8 5)))

